package main

import (
	"fmt"
	"sync"
	"time"
)

var lock sync.Mutex

// 匿名结构体，定义并初始化赋值
// 嵌入式锁（Embedded lock）的场景适合使用匿名结构体
var msgBox = struct {
	message  string
	isEmpty  bool
	sendCond *sync.Cond
	recvCond *sync.Cond
}{
	isEmpty: true,
	sendCond: sync.NewCond(&lock),
	recvCond: sync.NewCond(&lock),
}

// 用于设置消息的函数
func send(id, index int) {
	lock.Lock()
	for !msgBox.isEmpty {
		msgBox.sendCond.Wait()
	}
	msg := fmt.Sprintf("msg: [%d-%d]", id, index)
	msgBox.message = msg
	fmt.Printf("发送消息[%d-%d]: %s\t", id, index, msg)
	msgBox.isEmpty = false
	lock.Unlock()
	msgBox.recvCond.Broadcast()
}

// 用于读取消息的函数
func recv(id, index int) {
	lock.Lock()
	for msgBox.isEmpty {
		msgBox.recvCond.Wait()
	}
	msg := msgBox.message
	msgBox.message = ""
	fmt.Printf("接收消息[%d-%d]: %s\n", id, index, msg)
	msgBox.isEmpty = true
	lock.Unlock()
	msgBox.sendCond.Broadcast()
}

func main() {
	done := make(chan struct{})
	count := 5

	// 启动一个goroutine用于发送
	go func(id, count int) {
		defer func() {
			done <- struct{}{}
		}()
		for i := 0; i < count; i++ {
			time.Sleep(time.Millisecond * 100)
			send(id, i)
		}
	}(0, count * 2)

	// 启动两个goroutine用于接收
	go func(id, count int) {
		defer func() {
			done <- struct{}{}
		}()
		for i := 0; i < count; i++ {
			time.Sleep(time.Millisecond * 300)
			recv(id, i)
		}
	}(1, count)
	go func(id, count int) {
		defer func() {
			done <- struct{}{}
		}()
		for i := 0; i < count; i++ {
			time.Sleep(time.Millisecond * 400)
			recv(id, i)
		}
	}(2, count)

	<- done
	<- done
	<- done
	fmt.Println("Over")
}